#include "GLDriver.h"


namespace mpgl_engine{ namespace driver { 

	GLDriver::GLDriver( GLApp* app, 
			bool enableLogicThread, 
			bool enableNetworkThread)
	{
		// 1.	Set the application reference
		m_glApp = app;

		// 2.	Set the threading flags
		m_networkThreadingEnabled = enableNetworkThread;
		m_logicThreadingEnabled = enableLogicThread;

		//3a.	Set the base console
		m_console = new GlConsole();

		//3b.	Set the Events static base console to the drivers
		Event::SetErrorHandler(m_console);

		//3c.	If the application is !=NULL, set console
		if (m_glApp != NULL)
			m_glApp->SetConsole(m_console);


		//4a.	Create the thread pool manager
		m_threadPool = new ThreadPoolManager();

		//4b.	If logic updates are threaded.
		if (m_logicThreadingEnabled)
		{
			m_networkThread = new NetworkThread();
		}
		else
		{
			m_networkThread = NULL;
		}

		//4c.	If the network manager is threaded.
		if (m_networkThreadingEnabled)
		{
			m_logicThread = new LogicThread();
		}
		else
		{
			m_logicThread = NULL;
		}
#if (GL_DRIVER_DEBUG >= 1)
		if (m_console != NULL)
		{
			string msg = "[MPGL::Driver] ";
			msg += "Constructed";
			m_console->WriteMessage(msg);
		}
#endif
	}
		

	GLDriver::~GLDriver()
	{ 
		if (m_glApp != NULL) {
			delete m_glApp;
		}
		if (m_threadPool != NULL){
			delete m_threadPool;
		}
#if (GL_DRIVER_DEBUG >= 1)
		if (m_console != NULL)
		{
			string msg = "[MPGL::Driver] ";
			msg += "Destructed";
			m_console->WriteMessage(msg);
		}
#endif
		if (m_console != NULL){
			delete m_console;
		}
	}

	void GLDriver::SetApplication(GLApp* app)
	{ 
		m_glApp = app;
		if (m_glApp != NULL)
			m_glApp->SetConsole(m_console);
	}

	int GLDriver::Run()
	{
		m_console->WriteMessage("[MPGL::Driver] Loading GLFW Libraries");

		//Initialize the console handler
		InitializeConsoleHandler();

		//Initialize the GLFW library
		if (!glfwInit())
		{
			m_console->WriteError(
				"GLDriver::Run - Could not Initialize GLFW");
			return -1;
		}

		//Initialize the thread pool
		InitializeThreadPool();

		//Initialize the application
#if (GL_DRIVER_DEBUG >= 1)
		if (m_console != NULL)
		{
			string msg = "[MPGL::Driver] ";
			msg += "Initializing the Application ";
			m_console->WriteMessage(msg);
		}
#endif
		m_glApp->Initialize();

#if (GL_DRIVER_DEBUG >= 1)
		if (m_console != NULL)
		{
			string msg = "[MPGL::Driver] ";
			msg += "Loading the Applications Content ";
			m_console->WriteMessage(msg);
		}
#endif
		m_glApp->LoadContent();

		//Add Threads before we start running
		if (m_logicThread != NULL){
			m_threadPool->AddThread(m_logicThread);
#if (GL_DRIVER_DEBUG >= 1)
			if (m_console != NULL)
			{
				string msg = "[MPGL::Driver] ";
				msg += "Added Logic Thread";
				m_console->WriteMessage(msg);
			}
#endif
		}
		if (m_networkThread != NULL)
		{
			//Link the network thread to the network manager
			// before starting.
			m_networkThread->SetNetworkManager(	
				m_glApp->GetNetworkManager());
			m_threadPool->AddThread(m_networkThread);
#if (GL_DRIVER_DEBUG >= 1)
			if (m_console != NULL)
			{
				string msg = "[MPGL::Driver] ";
				msg += "Added Network Thread";
				m_console->WriteMessage(msg);
			}
#endif
		}

#if (GL_DRIVER_DEBUG >= 1)
		if (m_console != NULL)
		{
			string msg = "[MPGL::Driver] ";
			msg += "RUN APPLICATION ====================================";
			m_console->WriteMessage(msg);
		}
#endif

		//Update the application
		while(m_glApp->IsRunning())
		{
			m_glApp->Update();
			if (m_logicThread == NULL)
				m_glApp->UpdateLogic();
			m_glApp->Draw();
		}

		//Stop operating threads after running
		m_logicThread->RequestStop();
		m_networkThread->RequestStop();

#if (GL_DRIVER_DEBUG >= 1)
		if (m_console != NULL)
		{
			string msg = "[MPGL::Driver] ";
			msg += "END APPLICATION ====================================";
			m_console->WriteMessage(msg);
		}
#endif

#if (GL_DRIVER_DEBUG >= 1)
		if (m_console != NULL)
		{
			string msg = "[MPGL::Driver] ";
			msg += "Unloading the Applications Content";
			m_console->WriteMessage(msg);
		}
#endif
		//m_renderThread->RequestStop();
		m_glApp->UnloadContent();

#if (GL_DRIVER_DEBUG >= 1)
		if (m_console != NULL)
		{
			string msg = "[MPGL::Driver] ";
			msg += "Uninitializing the Application";
			m_console->WriteMessage(msg);
		}
#endif
		//Uninitialize the application
		m_glApp->Uninitialize();

		//Terminate the GLFW library and quit
		glfwTerminate();
		return 0;
	}
	
	void GLDriver::InitializeConsoleHandler()
	{
		//Set the app to this console handler
		m_glApp->SetConsole(m_console);
	}

	void GLDriver::InitializeThreadPool()
	{

	}

	void GLDriver::InitializeThreads()
	{

	}

}}